use crate::common::Response;
use axum::response::IntoResponse;
use thiserror::Error;

#[derive(Error, Debug)]
pub enum AppError {
    #[error("sql error:{0}")]
    SqlxError(#[from] sqlx::Error),

    #[error("create message error:{0}")]
    CreateMessageError(String),

    #[error("upload file error:{0}")]
    UploadFileError(String),

    #[error("io error:{0}")]
    IoError(#[from] std::io::Error),

    #[error("user has exists")]
    UserHasExists,

    #[error("password hash error:{0}")]
    PasswordHashError(#[from] argon2::password_hash::Error),

    #[error("jwt error:{0}")]
    JwtError(#[from] jwt_simple::Error),

    #[error("automatic error {0}")]
    AuthorityError(String),

    #[error("insert file error:{0}")]
    InsertFileError(String),

    #[error("chat error:{0}")]
    ChatError(String),
}

impl IntoResponse for AppError {
    fn into_response(self) -> axum::response::Response {
        let body = match self {
            AppError::ChatError(_) => {
                Response::<String>::fail(500, "chat error".to_string(), "fail".to_string())
            }
            AppError::InsertFileError(_) => {
                Response::<String>::fail(500, "insert file error".to_string(), "fail".to_string())
            }
            AppError::SqlxError(e) => {
                Response::<String>::fail(500, e.to_string(), "fail".to_string())
            }
            AppError::CreateMessageError(_) => Response::<String>::fail(
                500,
                "create message error".to_string(),
                "fail".to_string(),
            ),
            AppError::UploadFileError(_) => {
                Response::<String>::fail(500, "upload file error".to_string(), "fail".to_string())
            }
            AppError::IoError(_) => {
                Response::<String>::fail(500, "io error".to_string(), "fail".to_string())
            }
            AppError::UserHasExists => {
                Response::<String>::fail(400, "user has exists".to_string(), "fail".to_string())
            }
            AppError::PasswordHashError(_) => {
                Response::<String>::fail(500, "password hash error".to_string(), "fail".to_string())
            }
            AppError::JwtError(_) => {
                Response::<String>::fail(500, "jwt error".to_string(), "fail".to_string())
            }
            AppError::AuthorityError(_) => {
                Response::<String>::fail(401, "email not exists".to_string(), "fail".to_string())
            }
        };
        axum::response::Response::builder()
            .status(200)
            .body(axum::body::Body::from(
                serde_json::to_string(&body).unwrap(),
            ))
            .unwrap()
    }
}
